package com.xyht.sca_s.student_manage_system.modules.advanceRegistration.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ExceptionCast;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.ApiModelUtil;
import com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil;
import com.xyht.sca_s.student_manage_system.common.util.TimeUtil;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.RxAdvanceRegistrationOrg;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.RxAdvanceRegistrationPaymentItem;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.RxAdvanceRegistrationStudentInfo;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.req.RxAdvanceRegistrationStudentInfoReq;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.req.RxAdvanceRegistrationStudentPaymentReq;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.req.SmsAdvanceRegistrationPaymentRecordExportReq;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.req.WxCodeReq;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.entity.resp.*;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.mapper.RxAdvanceRegistrationOrgMapper;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.mapper.RxAdvanceRegistrationPaymentItemMapper;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.mapper.RxAdvanceRegistrationStudentInfoMapper;
import com.xyht.sca_s.student_manage_system.modules.advanceRegistration.service.RxAdvanceRegistrationStudentInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.entity.SmsWnsChargePaymentRecord;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.entity.resp.PrepayPaymentResp;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.entity.resp.SmsWnsChargePaymentRecordResp;
import com.xyht.sca_s.student_manage_system.modules.chargePayment.mapper.SmsWnsChargePaymentRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.config.WxPayConfig;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.PrepayPaymentReq;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.entity.WxPayFunctions;
import com.xyht.sca_s.student_manage_system.modules.payment.wxpay.util.WxPayUtil;
import com.xyht.sca_s.student_manage_system.modules.wx.util.WeChatUtil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.advanceRegistration.constant.IsPayConstant.IS_PAY;
import static com.xyht.sca_s.student_manage_system.modules.advanceRegistration.constant.IsPayConstant.IS_PAY_NOT;
import static com.xyht.sca_s.student_manage_system.modules.chargePayment.constant.SmsWnsChargePaymentRecordConstant.*;
import static com.xyht.sca_s.student_manage_system.modules.signUp.constant.SmsSignUpCommonConstant.PER_SHEET_NUM;

/**
 * <p>
 * 预报名学生信息 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2024-04-10
 */
@Service
public class RxAdvanceRegistrationStudentInfoServiceImpl extends ServiceImpl<RxAdvanceRegistrationStudentInfoMapper, RxAdvanceRegistrationStudentInfo> implements RxAdvanceRegistrationStudentInfoService {

    @Resource
    private RxAdvanceRegistrationStudentInfoMapper rxAdvanceRegistrationStudentInfoMapper;
    @Resource
    private RxAdvanceRegistrationOrgMapper rxAdvanceRegistrationOrgMapper;
    @Resource
    private RxAdvanceRegistrationPaymentItemMapper rxAdvanceRegistrationPaymentItemMapper;
    @Resource
    private SmsWnsChargePaymentRecordMapper smsWnsChargePaymentRecordMapper;
    @Resource
    private WxMaService wxMaService;
    @Resource
    private WeChatUtil weChatUtil;
    @Resource
    private WxPayUtil wxPayUtil;
    @Resource
    private ApiModelUtil apiModelUtil;
    @Override
    public ResponseResult addAdvanceRegistrationStudentInfo(RxAdvanceRegistrationStudentInfoReq addReq) {
        if (isNullOrEmpty(addReq.getPaymentItemId(),addReq.getOrgId(),addReq.getName(),
                addReq.getIdCard(),addReq.getTel(),addReq.getRemark())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //校验组织
        RxAdvanceRegistrationOrg advanceRegistrationOrg = rxAdvanceRegistrationOrgMapper.selectById(addReq.getOrgId());
        if (isNullOrEmpty(advanceRegistrationOrg)) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_ORG_NOT_EXIST);
        }
        //校验收费项
        RxAdvanceRegistrationPaymentItem rxAdvanceRegistrationPaymentItem = rxAdvanceRegistrationPaymentItemMapper.selectById(addReq.getPaymentItemId());
        if (isNullOrEmpty(rxAdvanceRegistrationPaymentItem)) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_PAYMENT_ITEM_NOT_EXIST);
        }
        //校验身份证和电话
        boolean validIDCard = ParamCheckUtil.isValidIDCard(addReq.getIdCard());
        if (!validIDCard) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_STUDENT_ID_CARD_ERR);
        }
        boolean validPhone = ParamCheckUtil.isValidPhone(addReq.getTel());
        if (!validPhone) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_TEL_ERR);
        }
        RxAdvanceRegistrationStudentInfo rxAdvanceRegistrationStudentInfo = new RxAdvanceRegistrationStudentInfo();
        BeanUtils.copyProperties(addReq,rxAdvanceRegistrationStudentInfo);
        rxAdvanceRegistrationStudentInfoMapper.insert(rxAdvanceRegistrationStudentInfo);
        return CommonResult.success();
    }

    @Override
    public ResponseResult getStuPaymentInfoList(Integer pageNum, Integer pageSize, String searchStr, String orgId, String startDate, String endDate, String middleSchoolId) {
        Page<SmsWnsChargePaymentRecord> page = new Page<>(pageNum,pageSize);
        LambdaQueryWrapper<SmsWnsChargePaymentRecord> lambdaQueryWrapper = new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                .eq(SmsWnsChargePaymentRecord::getType,CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                .isNotNull(SmsWnsChargePaymentRecord::getPaymentAmount)
                .isNotNull(SmsWnsChargePaymentRecord::getPaymentTime)
                .orderByDesc(SmsWnsChargePaymentRecord::getPaymentTime);
        if (!isNullOrEmpty(searchStr)) {
            List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                    .and(i -> i.like(RxAdvanceRegistrationStudentInfo::getIdCard, searchStr)
                            .or()
                            .like(RxAdvanceRegistrationStudentInfo::getName, searchStr)
                            .or()
                            .like(RxAdvanceRegistrationStudentInfo::getTel, searchStr)
                            .or()
                            .like(RxAdvanceRegistrationStudentInfo::getSex, searchStr)))
                    .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
            if (studentIdList.isEmpty()) {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
            } else {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
            }
        }
        if (!isNullOrEmpty(orgId)) {
            List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                            .eq(RxAdvanceRegistrationStudentInfo::getOrgId, orgId))
                            .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
            if (studentIdList.isEmpty()) {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
            } else {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
            }
        }
        if (!isNullOrEmpty(middleSchoolId)) {
            List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                    .eq(RxAdvanceRegistrationStudentInfo::getMiddleSchoolId, middleSchoolId))
                    .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
            if (studentIdList.isEmpty()) {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
            } else {
                lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
            }
        }
        if (!isNullOrEmpty(startDate)) {
            lambdaQueryWrapper.ge(SmsWnsChargePaymentRecord::getUpdateTime,startDate);
        }
        if (!isNullOrEmpty(endDate)) {
            lambdaQueryWrapper.le(SmsWnsChargePaymentRecord::getUpdateTime,endDate);
        }
        smsWnsChargePaymentRecordMapper.selectPage(page, lambdaQueryWrapper);
        List<SmsAdvanceRegistrationPaymentRecordResp> list = page.getRecords()
                .stream().map(paymentRecord -> {
                    SmsAdvanceRegistrationPaymentRecordResp resp = new SmsAdvanceRegistrationPaymentRecordResp();
                    RxAdvanceRegistrationStudentInfoResp studentInfoResp = new RxAdvanceRegistrationStudentInfoResp();
                    RxAdvanceRegistrationStudentInfo studentInfo = rxAdvanceRegistrationStudentInfoMapper.selectById(paymentRecord.getEventId());
                    if (!isNullOrEmpty(studentInfo)) {
                        BeanUtils.copyProperties(studentInfo,studentInfoResp);
                        resp.setStudentInfo(studentInfoResp);
                    }
                    resp.setPaymentTime(paymentRecord.getPaymentTime());
                    return resp;
                })
                .collect(Collectors.toList());
        return CommonResult.success(list,(int)page.getTotal());
    }

    @Override
    @Async
    public Future<ResponseResult> exportStuPaymentInfo(SmsAdvanceRegistrationPaymentRecordExportReq exportReq, HttpServletResponse response) {
        try{

            LambdaQueryWrapper<SmsWnsChargePaymentRecord> lambdaQueryWrapper = new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                    .eq(SmsWnsChargePaymentRecord::getType,CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                    .isNotNull(SmsWnsChargePaymentRecord::getPaymentAmount)
                    .orderByDesc(SmsWnsChargePaymentRecord::getUpdateTime);
            if (!isNullOrEmpty(exportReq.getName())) {
                List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                        .like(RxAdvanceRegistrationStudentInfo::getName, exportReq.getName()))
                        .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
                if (studentIdList.isEmpty()) {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
                } else {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
                }
            }

            if (!isNullOrEmpty(exportReq.getIdCard())) {
                List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                        .like(RxAdvanceRegistrationStudentInfo::getIdCard, exportReq.getIdCard()))
                        .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
                if (studentIdList.isEmpty()) {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
                } else {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
                }
            }

            if (!isNullOrEmpty(exportReq.getTel())) {
                List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                        .like(RxAdvanceRegistrationStudentInfo::getTel, exportReq.getTel()))
                        .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
                if (studentIdList.isEmpty()) {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
                } else {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
                }
            }

            if (!isNullOrEmpty(exportReq.getOrgId())) {
                List<String> studentIdList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                        .eq(RxAdvanceRegistrationStudentInfo::getOrgId, exportReq.getOrgId()))
                        .stream().map(RxAdvanceRegistrationStudentInfo::getId).collect(Collectors.toList());
                if (studentIdList.isEmpty()) {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,"");
                } else {
                    lambdaQueryWrapper.in(SmsWnsChargePaymentRecord::getEventId,studentIdList);
                }
            }

            if (!isNullOrEmpty(exportReq.getStartDate())) {
                lambdaQueryWrapper.ge(SmsWnsChargePaymentRecord::getUpdateTime,exportReq.getStartDate());
            }
            if (!isNullOrEmpty(exportReq.getEndDate())) {
                lambdaQueryWrapper.le(SmsWnsChargePaymentRecord::getUpdateTime,exportReq.getEndDate());
            }
            List<SmsAdvanceRegistrationPaymentRecordExportResp> list = smsWnsChargePaymentRecordMapper.selectList(lambdaQueryWrapper)
                    .stream().map(paymentRecord -> {
                        SmsAdvanceRegistrationPaymentRecordExportResp resp = new SmsAdvanceRegistrationPaymentRecordExportResp();
                        RxAdvanceRegistrationStudentInfo studentInfo = rxAdvanceRegistrationStudentInfoMapper.selectById(paymentRecord.getEventId());
                        if (!isNullOrEmpty(studentInfo)) {
                            BeanUtils.copyProperties(studentInfo,resp);
                            resp.setPaymentTime(paymentRecord.getPaymentTime());
                        }
                        return resp;
                    })
                    .collect(Collectors.toList());

            //表头数据
            String[] header = exportReq.getLimitColumn().toArray(new String[0]);
            double sheetNum;
            //声明一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook();
            if (list.size() > 0) {
                sheetNum = Math.ceil((double) list.size() / PER_SHEET_NUM);
                for (int k = 0; k < sheetNum; k++) {
                    //生成一个表格，设置表格名称为"资源导出表"
                    HSSFSheet sheet = workbook.createSheet("学生预报名缴费信息导出表" + (k + 1));

                    //设置表格列宽度为10个字节
                    sheet.setDefaultColumnWidth(12);
                    //创建标题的显示样式
                    HSSFCellStyle headerStyle = workbook.createCellStyle();
                    headerStyle.setFillForegroundColor(IndexedColors.YELLOW.index);
                    headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

                    HSSFFont f = workbook.createFont();
                    f.setFontHeightInPoints((short) 10);//字号
                    f.setBold(true);//加粗
                    headerStyle.setFont(f);
                    //创建第一行表头
                    HSSFRow headrow = sheet.createRow(0);

                    //遍历添加表头(下面模拟遍历学生，也是同样的操作过程)
                    for (int i = 0; i < header.length + 1; i++) {
                        //创建一个单元格
                        HSSFCell cell = headrow.createCell(i);

                        if (i == 0) {
                            //创建一个内容对象
                            HSSFRichTextString text = new HSSFRichTextString("序号");
                            //将内容对象的文字内容写入到单元格中
                            cell.setCellValue(text);
                            cell.setCellStyle(headerStyle);
                            continue;
                        }
                        //创建一个内容对象
                        String header1 = apiModelUtil.getFieldValueByFieldName(SmsAdvanceRegistrationPaymentRecordExportResp.class, header[i - 1]);
                        HSSFRichTextString text = new HSSFRichTextString(header1);

                        //将内容对象的文字内容写入到单元格中
                        cell.setCellValue(text);
                        cell.setCellStyle(headerStyle);
                    }


                    int range = PER_SHEET_NUM;
                    if (k + 1 == sheetNum) {
                        range = list.size() - (PER_SHEET_NUM) * k;
                    }
                    for (int i = 0; i < range; i++) {
                        //创建一行
                        HSSFRow row1 = sheet.createRow(i + 1);
                        SmsAdvanceRegistrationPaymentRecordExportResp paymentRecordResp = list.get((PER_SHEET_NUM) * k + i);
                        Map map = JSONObject.parseObject(JSON.toJSONString(paymentRecordResp), Map.class);
                        row1.createCell(0).setCellValue(new HSSFRichTextString(i + 1 + ""));
                        for (int j = 0; j < header.length; j++) {
                            String rowContent = "";
                            if(!isNullOrEmpty(map.get(header[j]))) {
                                if (map.get(header[j]) instanceof Long) {
                                    rowContent = TimeUtil.DateAllHanZi((long) map.get(header[j]));
                                } else {
                                    rowContent = String.valueOf(map.get(header[j]));
                                }
                            }
                            row1.createCell(j + 1).setCellValue(new HSSFRichTextString(rowContent));
                        }

                    }
                }
            }

            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("学生预报名缴费信息导出表.xlsx", "utf-8"));
            response.setCharacterEncoding("utf-8");
            response.setHeader("file-type", "download");
            response.setHeader("file-name", URLEncoder.encode("学生预报名缴费信息导出表.xlsx", "utf-8"));
            response.setHeader("Access-Control-Expose-Headers", "file-type,file-name");
            //刷新缓冲
            response.flushBuffer();
            //workbook将Excel写入到response的输出流中，供页面下载
            OutputStream os = response.getOutputStream();
            workbook.write(os);

            workbook.close();
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return new AsyncResult<>(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        return null;
    }

    @Override
    @Transactional
    public ResponseResult payment(RxAdvanceRegistrationStudentPaymentReq req) {

        //type为2时招生预支付
        if (req.getType() == null || req.getType() != CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        //存学生信息
        if (isNullOrEmpty(req.getPaymentItemId(),req.getOrgId(),req.getName(),req.getMiddleSchool(),req.getMiddleSchoolId(),req.getMiddleSchoolClasses(),
                req.getIdCard(),req.getTel(),req.getOpenId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验身份证和电话
        boolean validIDCard = ParamCheckUtil.isValidIDCard(req.getIdCard());
        if (!validIDCard) {
            return CommonResult.failed(CommonCodeEnum.ENROLLMENT_MANAGEMENT_STUDENT_ID_CARD_ERR);
        }
        boolean validPhone = ParamCheckUtil.isValidPhone(req.getTel());
        if (!validPhone) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_TEL_ERR);
        }
        //校验组织
        RxAdvanceRegistrationOrg advanceRegistrationOrg = rxAdvanceRegistrationOrgMapper.selectById(req.getOrgId());
        if (isNullOrEmpty(advanceRegistrationOrg)) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_ORG_NOT_EXIST);
        }
        //校验收费项
        RxAdvanceRegistrationPaymentItem rxAdvanceRegistrationPaymentItem = rxAdvanceRegistrationPaymentItemMapper.selectById(req.getPaymentItemId());
        if (isNullOrEmpty(rxAdvanceRegistrationPaymentItem)) {
            return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_PAYMENT_ITEM_NOT_EXIST);
        }
        //获取收费项金额
        BigDecimal paymentAmount = rxAdvanceRegistrationPaymentItem.getPaymentAmount();
        // 获取商户集合
        List<WxPayFunctions> wxPayFunctionsList = WxPayConfig.wxPayFunctionsList;
        if (wxPayFunctionsList.isEmpty()) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.FAIL));
        }
        // 校验前端传入的商户Type
        Integer wxPayFunctionType = rxAdvanceRegistrationPaymentItem.getWxPayFunctionType();
        if (wxPayFunctionType == null || wxPayFunctionType <= 0
                || wxPayFunctionType > wxPayFunctionsList.size() + 1) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.INVALID_PARAM));
        }
        // 获取用户选择的商户
        WxPayFunctions wxPayFunction = wxPayFunctionsList.get(wxPayFunctionType - 1);

        //构造学生信息
        String studentId = null;
        List<RxAdvanceRegistrationStudentInfo> studentInfoList = rxAdvanceRegistrationStudentInfoMapper.selectList(new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                .eq(RxAdvanceRegistrationStudentInfo::getIdCard, req.getIdCard()));
        if (!studentInfoList.isEmpty()) {
            studentId = studentInfoList.get(0).getId();
        }


        //构造学生信息
        RxAdvanceRegistrationStudentInfo rxAdvanceRegistrationStudentInfo = new RxAdvanceRegistrationStudentInfo();
        //构造缴费信息
        SmsWnsChargePaymentRecord paymentRecord = new SmsWnsChargePaymentRecord();
        //构造预支付码给前端
        PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse;
        PrepayPaymentResp prepayPaymentResp = new PrepayPaymentResp();
        if (!isNullOrEmpty(studentId)) {//有学生信息

            RxAdvanceRegistrationStudentInfo studentInfo = rxAdvanceRegistrationStudentInfoMapper.selectById(studentId);
            if (isNullOrEmpty(studentInfo)) {
                return CommonResult.failed(CommonCodeEnum.ADVANCE_REGISTRATION_DATA_UPDATE);
            }
            //修改学生信息
            BeanUtils.copyProperties(req, rxAdvanceRegistrationStudentInfo);
            studentInfo.setPaymentItemAmount(paymentAmount);
            rxAdvanceRegistrationStudentInfoMapper.update(rxAdvanceRegistrationStudentInfo, new LambdaQueryWrapper<RxAdvanceRegistrationStudentInfo>()
                        .eq(RxAdvanceRegistrationStudentInfo::getId, studentId));

            //查该学生的缴费记录
            List<SmsWnsChargePaymentRecord> paymentRecordList = smsWnsChargePaymentRecordMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                    .eq(SmsWnsChargePaymentRecord::getType, CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                    .eq(SmsWnsChargePaymentRecord::getEventId,studentId));
            if (paymentRecordList.isEmpty()) {
                prepayWithRequestPaymentResponse = insertPaymentRecordAndOrder(paymentRecord,req, paymentAmount, studentId, wxPayFunction);
                if (prepayWithRequestPaymentResponse == null) {
                    return CommonResult.failed(CommonCodeEnum.WNS_PAYMENT_RECORD_SAVE_FAIL);
                }
            } else {
                //数据库已存在的值
                BigDecimal paymentAmountData = paymentRecordList.get(0).getPaymentAmount();
                if (!isNullOrEmpty(paymentAmountData)) {
                    prepayPaymentResp.setIsPay(IS_PAY);
                    return CommonResult.success(prepayPaymentResp);
                }
                //获取已存在的支付信息预支付码给前端
                //校验缴费项金额是否更改
                BigDecimal paymentItemAmount = studentInfo.getPaymentItemAmount();
                //金额修改不相等则重新发起
                if (paymentAmount.compareTo(paymentItemAmount) != 0) {
                    //缴费记录重新生成
                    //先删除旧的预支付记录
                    smsWnsChargePaymentRecordMapper.delete(new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                            .eq(SmsWnsChargePaymentRecord::getType, CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                            .eq(SmsWnsChargePaymentRecord::getEventId,studentId));
                    // 生成新的支付记录
                    prepayWithRequestPaymentResponse = insertPaymentRecordAndOrder(paymentRecord,req, paymentAmount, studentId, wxPayFunction);
                    if (prepayWithRequestPaymentResponse == null) {
                        return CommonResult.failed(CommonCodeEnum.WNS_PAYMENT_RECORD_SAVE_FAIL);
                    }

                }else {
                    // 之前的数据发起支付
                    prepayWithRequestPaymentResponse = JSON.parseObject(paymentRecordList.get(0).getPrepayId(), PrepayWithRequestPaymentResponse.class);
                }
            }
        } else {//没有学生信息
            //新增学生信息
            BeanUtils.copyProperties(req,rxAdvanceRegistrationStudentInfo);
            rxAdvanceRegistrationStudentInfo.setPaymentItemAmount(paymentAmount);
            rxAdvanceRegistrationStudentInfoMapper.insert(rxAdvanceRegistrationStudentInfo);
            studentId = rxAdvanceRegistrationStudentInfo.getId();
            if (isNullOrEmpty(studentId)) {
                return CommonResult.failed(CommonCodeEnum.FAIL);
            }

            // 生成新的支付记录
            prepayWithRequestPaymentResponse = insertPaymentRecordAndOrder(paymentRecord,req, paymentAmount, studentId, wxPayFunction);
            if (prepayWithRequestPaymentResponse == null) {
                return CommonResult.failed(CommonCodeEnum.WNS_PAYMENT_RECORD_SAVE_FAIL);
            }

        }


        // 移除无效数据(超过半小时未支付)
        List<SmsWnsChargePaymentRecord> ivalidPaymentRecordList = smsWnsChargePaymentRecordMapper.selectList(new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                .le(SmsWnsChargePaymentRecord::getExpireTime, new Date())
                .eq(SmsWnsChargePaymentRecord::getType,CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                .isNull(SmsWnsChargePaymentRecord::getPaymentTime));
        if (!ivalidPaymentRecordList.isEmpty()) {
            //删除预报名学生信息
            List<String> stuIdList = ivalidPaymentRecordList.stream().map(SmsWnsChargePaymentRecord::getEventId).collect(Collectors.toList());
            rxAdvanceRegistrationStudentInfoMapper.deleteBatchIds(stuIdList);
            //删除未缴费记录
            List<String> ivalidPaymentRecordIdList = ivalidPaymentRecordList.stream().map(SmsWnsChargePaymentRecord::getId).distinct().collect(Collectors.toList());
            smsWnsChargePaymentRecordMapper.deleteBatchIds(ivalidPaymentRecordIdList);

        }


        // 构造返回数据
        SmsWnsChargePaymentRecordResp paymentRecordResp = new SmsWnsChargePaymentRecordResp();
        BeanUtils.copyProperties(paymentRecord, paymentRecordResp);
        // 设置预支付信息
//        PrepayPaymentResp prepayPaymentResp = new PrepayPaymentResp();
        BeanUtils.copyProperties(prepayWithRequestPaymentResponse, prepayPaymentResp);
        prepayPaymentResp.setTimestamp(prepayWithRequestPaymentResponse.getTimeStamp());
        paymentRecordResp.setPrepayPaymentResp(prepayPaymentResp);


        // 记录预支付数据
        paymentRecord.setPrepayId(JSON.toJSONString(prepayPaymentResp));
        paymentRecord.setConfigName(wxPayFunction.getWxPayCommonConfig().getCONFIG_NAME());
        smsWnsChargePaymentRecordMapper.updateById(paymentRecord);
        prepayPaymentResp.setIsPay(IS_PAY_NOT);
        return CommonResult.success(prepayPaymentResp);
    }

    /**
     *
     * @param paymentRecord 缴费记录
     * @param req 前端传的参数
     * @param paymentAmount 收费项金额
     * @param studentId 学生id
     * @param wxPayFunction 支付方式
     * @return 微信预支付返回参数
     */
    private PrepayWithRequestPaymentResponse insertPaymentRecordAndOrder(SmsWnsChargePaymentRecord paymentRecord,RxAdvanceRegistrationStudentPaymentReq req, BigDecimal paymentAmount,
                                                                         String studentId,WxPayFunctions wxPayFunction) {
        // 设置过期时间(订单失效时间)
        Date timeExpire = TimeUtil.AddMinute(new Date(), 30);
        // 生成新的支付记录
        // 设置过期时间 = 当前时间 + 30min
        paymentRecord.setExpireTime(timeExpire);
        paymentRecord.setType(CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY);
        paymentRecord.setMode(CHARGE_PAYMENT_RECORD_MODE_ONLINE);
        paymentRecord.setEventId(studentId);
        paymentRecord.setUserId(req.getOpenId());
        smsWnsChargePaymentRecordMapper.insert(paymentRecord);
        if (isNullOrEmpty(paymentRecord.getId())) {
            return null;
        }

        // 发起支付
        PrepayPaymentReq prepayPaymentReq = new PrepayPaymentReq();
        prepayPaymentReq.setDescription(CHARGE_PAYMENT_RECORD_TYPE_DES_NEW_STU_PREPAY);
        prepayPaymentReq.setOutTradeNo(paymentRecord.getId());
        prepayPaymentReq.setTimeExpire(timeExpire);
        // 设置订单金额 单位：分(订单金额 = 原金额(元) * 100)
        int total = paymentAmount.multiply(BigDecimal.valueOf(100)).intValue();
        prepayPaymentReq.setTotal(total);
        prepayPaymentReq.setOpenId(req.getOpenId());

        //订单预支付 生成预支付码给前端
        PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse = wxPayUtil.prepayPayment(prepayPaymentReq,wxPayFunction);
        if (prepayWithRequestPaymentResponse == null) {
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WNS_PAYMENT_PRE_PAYMENT_INFO_MISSING));
        }
        return prepayWithRequestPaymentResponse;
    }

    @Override
    public ResponseResult wxAuthorize(WxCodeReq addReq) {
        WxInfoResp wxInfoResp = new WxInfoResp();
        try {
            WxMaJscode2SessionResult sessionResult = weChatUtil.getSessionKey(wxMaService, addReq.getCode());
            String openId = sessionResult.getOpenid();
            String sessionKey = sessionResult.getSessionKey();
            if (openId.isEmpty() || sessionKey.isEmpty()) {
                ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WX_CHECK_FAIL));
            }
            wxInfoResp.setOpenId(openId);
            wxInfoResp.setSessionKey(sessionKey);
        } catch (Exception e) {
            e.printStackTrace();
            ExceptionCast.cast(CommonResult.failed(CommonCodeEnum.WX_CHECK_FAIL));
        }
        return CommonResult.success(wxInfoResp);
    }

    @Override
    public ResponseResult getStuIsPayment(String openId) {
        if (isNullOrEmpty(openId)) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        SmsStuIsPaymentResp stuIsPaymentResp = new SmsStuIsPaymentResp();
        RxAdvanceRegistrationStudentInfoResp studentInfoResp = new RxAdvanceRegistrationStudentInfoResp();

        //该用户是否缴费
        List<SmsWnsChargePaymentRecord> paymentRecordList = smsWnsChargePaymentRecordMapper.selectList(
                new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                        .eq(SmsWnsChargePaymentRecord::getType, CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                        .eq(SmsWnsChargePaymentRecord::getUserId, openId)
                        .isNotNull(SmsWnsChargePaymentRecord::getPaymentAmount));
        if (!paymentRecordList.isEmpty()) {//缴费
            stuIsPaymentResp.setIsPayment(true);
            String stuId = paymentRecordList.get(0).getEventId();
            if (stuId != null) {
                RxAdvanceRegistrationStudentInfo rxAdvanceRegistrationStudentInfo = rxAdvanceRegistrationStudentInfoMapper.selectById(stuId);
                BeanUtils.copyProperties(rxAdvanceRegistrationStudentInfo, studentInfoResp);
                stuIsPaymentResp.setStudentInfoResp(studentInfoResp);
            }
        } else {//未缴费
            List<SmsWnsChargePaymentRecord> notPaymentRecordList = smsWnsChargePaymentRecordMapper.selectList(
                    new LambdaQueryWrapper<SmsWnsChargePaymentRecord>()
                            .eq(SmsWnsChargePaymentRecord::getType, CHARGE_PAYMENT_RECORD_NEW_STU_PREPAY)
                            .eq(SmsWnsChargePaymentRecord::getUserId, openId)
                            .isNull(SmsWnsChargePaymentRecord::getPaymentAmount));
            if (!notPaymentRecordList.isEmpty()) {//缴费记录还没有过期
                String stuId = notPaymentRecordList.get(0).getEventId();
                if (stuId != null) {
                    RxAdvanceRegistrationStudentInfo rxAdvanceRegistrationStudentInfo = rxAdvanceRegistrationStudentInfoMapper.selectById(stuId);
                    BeanUtils.copyProperties(rxAdvanceRegistrationStudentInfo, studentInfoResp);
                    stuIsPaymentResp.setStudentInfoResp(studentInfoResp);
                }
            }
            stuIsPaymentResp.setIsPayment(false);

        }
        return CommonResult.success(stuIsPaymentResp);
    }
}
